package com.carrental.api.oms.service.impl;

import cn.dev33.satoken.annotation.SaCheckLogin;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.mail.MailUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.carrental.api.cms.domain.CmsCar;
import com.carrental.api.cms.service.ICmsCarService;
import com.carrental.api.common.exception.Assert;
import com.carrental.api.oms.domain.vo.OmsOrderVo;
import com.carrental.common.exception.OperationException;
import com.carrental.api.common.query.CommonQueryParam;
import com.carrental.api.common.utils.CommonQueryWrapper;
import com.carrental.api.oms.domain.OmsOrder;
import com.carrental.api.oms.domain.bo.OmsLendCheckPost;
import com.carrental.api.oms.domain.bo.OmsOrderBo;
import com.carrental.api.oms.domain.bo.OmsReturnCheckPost;
import com.carrental.api.oms.domain.vo.OmsOrderDetailVo;
import com.carrental.api.oms.mapper.OmsOrderMapper;
import com.carrental.api.oms.service.IOmsLendCheckService;
import com.carrental.api.oms.service.IOmsOrderService;
import com.carrental.api.oms.service.IOmsReturnCheckService;
import com.carrental.api.pms.service.IPmsStoreService;
import com.carrental.api.ums.service.IUmsUserService;
import com.carrental.common.enums.OrderStatusEnum;
import com.carrental.common.utils.OrderNumberUtil;
import com.carrental.common.utils.StpUmsUtil;
import com.carrental.sms.domain.SmsInfo;
import com.carrental.sms.servicce.AliyunSmsService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.Duration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 订单 服务实现类
 * </p>
 *
 * @author 梁毅
 * @since 2022-03-07 23:00:58
 */
@Service
@Slf4j
public class OmsOrderServiceImpl extends ServiceImpl<OmsOrderMapper, OmsOrder> implements IOmsOrderService {

    @Autowired
    private ICmsCarService carService;
    @Autowired
    private IOmsLendCheckService lendCheckService;
    @Autowired
    private IOmsReturnCheckService returnCheckService;
    @Autowired
    private IPmsStoreService storeService;
    @Autowired
    private IUmsUserService userService;
    @Autowired
    private OrderNumberUtil orderNumberUtil;
    @Autowired
    private AliyunSmsService aliyunSmsService;
    /**
     * 获取分页
     *
     * @param commonQueryParam 查询参数
     * @return 分页
     */
    @Override
    public IPage<OmsOrder> pageList(CommonQueryParam commonQueryParam) {
        return this.baseMapper.pageList(
                new Page<>(commonQueryParam.getCurrent(), commonQueryParam.getSize()),
                new CommonQueryWrapper<OmsOrder>(commonQueryParam).lambda()
                        .eq(OmsOrder::getIsDeleted, false)
        );
    }

    /**
     * 根绝门店获取订单分页
     *
     * @param commonQueryParam 查询参数
     * @return 分页
     */
    @Override
    public IPage<OmsOrder> pageListByStoreId(Long storeId, CommonQueryParam commonQueryParam) {
        return this.baseMapper.pageList(
                new Page<>(commonQueryParam.getCurrent(), commonQueryParam.getSize()),
                new CommonQueryWrapper<OmsOrder>(commonQueryParam).lambda()
                        .eq(OmsOrder::getStoreId, storeId)
                        .eq(OmsOrder::getIsDeleted, false)
        );
    }

    /**
     * 添加订单
     *
     * @param omsOrderPost 订单参数
     * @return 是否成功
     */
    @Override
    @SaCheckLogin()
    public Boolean create(OmsOrderBo omsOrderPost)  {
        CmsCar car = carService.detail(omsOrderPost.getCarId());
        BigDecimal depositPrice = new BigDecimal(String.valueOf(car.getDepositPrice()));
        BigDecimal rentalPrice = new BigDecimal(String.valueOf(car.getRentalPrice()));
        Duration between = LocalDateTimeUtil.between(omsOrderPost.getDriveStartDate(), omsOrderPost.getDriveEndDate());
        BigDecimal rentalDays = new BigDecimal(between.toDays());
        BigDecimal discount = new BigDecimal(String.valueOf(omsOrderPost.getDiscount()));
        //结算规则，折扣*(天数*租金) + 押金
        omsOrderPost.setTotalAmount(
                discount.multiply(
                        rentalDays.multiply(rentalPrice)
                ).add(depositPrice)
        );
        OmsOrder omsOrder = new OmsOrder();
        BeanUtils.copyProperties(omsOrderPost, omsOrder);
        //设置订单基本信息
        omsOrder.setStatus(OrderStatusEnum.BOOK.getStatus());
        omsOrder.setOrderNumber(orderNumberUtil.generateOrderNumber());
        omsOrder.setUserId(StpUmsUtil.getLoginIdAsLong());
        omsOrder.setDriveDays(String.valueOf(between.toDays()));
        if (!this.save(omsOrder)) {
            throw new OperationException("生成订单失败！");
        }
        //当前车辆必须为未租出，再变更车辆状态为租出
        carService.carLend(car.getCarId());
        String info= StrUtil.format("尊敬的 {} 先生/女士：您已预定车辆 {} ，请前往 {} 进行取车",userService.getMyInfo().getRealName(),omsOrder.getCarName(),omsOrder.getStoreName());
        //发送邮件给用户
        MailUtil.send(userService.getById(omsOrder.getUserId()).getEmail(), "秋名山租车-预定成功", info, false);
        return true;
    }

    /**
     * 逻辑删除
     *
     * @param id id
     * @return 是否成功
     */
    @Override
    public Boolean delete(Long id) {
        //先查询，再更新
        OmsOrder omsOrder = this.detail(id);
        Assert.notNull(omsOrder, "删除失败，无此订单！");
        omsOrder.setIsDeleted(true);
        if (!this.updateById(omsOrder)) {
            throw new OperationException("删除失败！");
        }
        return true;
    }

    /**
     * 修改订单信息
     *
     * @param id        id
     * @param omsOrderPost 订单参数
     * @return 是否成功
     */
    @Override
    public Boolean update(Long id, OmsOrderBo omsOrderPost) {
        //先查询，再更新
        OmsOrder omsOrder = this.getById(id);
        Assert.notNull(omsOrder, "修改失败，无此订单！");
        BeanUtils.copyProperties(omsOrderPost, omsOrder, "orderId");
        if (!this.updateById(omsOrder)) {
            throw new OperationException("修改订单信息失败！");
        }
        return true;
    }

    /**
     * 订车出车
     *
     * @param orderId       订单id
     * @param lendCheckPost 出车单参数
     * @return 是否成功
     */
    @Override
    public Boolean lendCheckOrder(Long orderId, OmsLendCheckPost lendCheckPost) {
        OmsOrder omsOrder = this.detail(orderId);
        Assert.notNull(omsOrder, "该订单不存在");
        if (!omsOrder.getStatus().equals(OrderStatusEnum.BOOK.getStatus())) {
            throw new OperationException("订单不为预订状态，无法出车");
        }
        //更新订单状态
        omsOrder.setStatus(OrderStatusEnum.LEND.getStatus());
        if (!this.updateById(omsOrder)) {
            throw new OperationException("订单出车失败！");
        }
        //创建出车检查单
        lendCheckService.create(lendCheckPost);
        return true;
    }

    /**
     * 订车还车
     *
     * @param orderId         订单id
     * @param returnCheckPost 还车单参数
     * @return 是否成功
     */
    @Override
    public Boolean returnCheckOrder(Long orderId, OmsReturnCheckPost returnCheckPost) {
        OmsOrder omsOrder = this.detail(orderId);
        Assert.notNull(omsOrder, "该订单不存在");
        if (!omsOrder.getStatus().equals(OrderStatusEnum.LEND.getStatus())) {
            throw new OperationException("订单不为出车状态，无法还车");
        }
        //更新订单状态
        omsOrder.setStatus(OrderStatusEnum.RETURN.getStatus());
        if (!this.updateById(omsOrder)) {
            throw new OperationException("订单还车失败！");
        }
        //更改车辆状态
        carService.carReturn(omsOrder.getCarId());
        //创建出车检查单
        returnCheckService.create(returnCheckPost);
        return true;
    }

    /**
     * 取消订单
     *
     * @param id id
     * @return 是否成功
     */
    @Override
    public Boolean cancel(Long id) {
        //先查询，再更新订单
        OmsOrder omsOrder = this.getById(id);
        Assert.notNull(omsOrder, "取消失败，该订单不存在！");
        if(!omsOrder.getStatus().equals(OrderStatusEnum.BOOK.getStatus())){
            throw new OperationException("订单正在进行中，如在用车过程中有疑问请联系门店");
        }
        //更新订单状态
        omsOrder.setStatus(OrderStatusEnum.CANCEL.getStatus());
        if (!this.updateById(omsOrder)) {
            throw new OperationException("修改订单信息失败！");
        }
        //释放订单车辆状态为归还
        if (!carService.carReturn(omsOrder.getCarId())) {
            throw new OperationException("车辆状态变更失败!");
        }
        String info= StrUtil.format("尊敬的 {} 先生/女士：您已取消车辆为 {} ,订单号为 {} 的订单，期待下次光临",userService.getMyInfo().getRealName(),omsOrder.getCarName(),omsOrder.getOrderNumber());
        //发送邮件给用户
        MailUtil.send(userService.getById(omsOrder.getUserId()).getEmail(), "秋名山租车-取消成功", info, false);
        return true;
    }

    /**
     * 查看订单信息
     *
     * @param id 订单参数
     * @return 订单信息
     */
    @Override
    public OmsOrder detail(Long id) {
        OmsOrder omsOrder = this.getById(id);
        Assert.notNull(omsOrder, "查询失败，无此订单");
        return omsOrder;
    }

    /**
     * 查看订单详情信息，包括换车单出车单
     * @param id 订单参数
     * @return 订单信息
     */
    @Override
    public OmsOrderDetailVo allDetail(Long id) {
        OmsOrderDetailVo orderDetailVo=new OmsOrderDetailVo();
        OmsOrder order=this.getById(id);
        orderDetailVo.setOrder(this.detail(order.getOrderId()));
        orderDetailVo.setCar(carService.detail(order.getCarId()));
        orderDetailVo.setLendCheck(lendCheckService.detailByOrderId(order.getOrderId()));
        orderDetailVo.setReturnCheck(returnCheckService.detailByOrderId(order.getOrderId()));
        orderDetailVo.setUser(userService.getById(order.getUserId()));
        orderDetailVo.setStore(storeService.detail(order.getStoreId()));
        return orderDetailVo;
    }

    /**
     * 获取列表
     *
     * @param commonQueryParam 查询参数
     * @return 分页
     */
    @Override
    public List<OmsOrder> list(CommonQueryParam commonQueryParam) {
        return this.list(
                new CommonQueryWrapper<OmsOrder>(commonQueryParam).lambda()
                        .eq(OmsOrder::getIsDeleted, false)
        );
    }

    /**
     * 获取列表
     *
     * @param commonQueryParam 查询参数
     * @return 分页
     */
    @Override
    public List<OmsOrderVo> myOrderList(CommonQueryParam commonQueryParam) {
        return this.baseMapper.myList(
            new CommonQueryWrapper<OmsOrder>(commonQueryParam)
                .eq("oms_order.user_id", StpUmsUtil.getLoginId())
                .eq("oms_order.is_deleted", false)
                .orderByDesc("oms_order.create_time")
        );
    }

}
